﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Core.DataAccess.IRepositories;

namespace Core.DataAccess.Repositories
{
    [Export(typeof(IAccountRepository))]
    public class AccountRepository : IAccountRepository
    {
        private Connection conn;

        public AccountRepository()
        {
            conn = new Connection();
        }

        public Account GetAccountByID(int AccountID)
        {
            Account account = null;

            using (MXHEntities context = conn.GetContext())
            {
                account = (from a in context.Accounts.Include("Profiles")
                           where a.AccountID == AccountID
                           select a).FirstOrDefault();

                if (account != null)
                {
                    SetNavigationalProperties(account);
                }
            }

            return account;
        }

        public Account GetAccountByEmail(string Email)
        {
            Account account = null;

            using (MXHEntities context = conn.GetContext())
            {
                account = (from a in context.Accounts.Include("Profiles")
                    where a.Email == Email
                    select a).FirstOrDefault();

                if (account != null)
                {
                    SetNavigationalProperties(account);
                }
            }
            return account;
        }

        public Account GetAccountByUsername(string Username)
        {
            Account account = null;

            using (MXHEntities context = conn.GetContext())
            {
                account = (from a in context.Accounts.Include("Profiles")
                    where a.Username == Username
                    select a).FirstOrDefault();

                if (account != null)
                {
                    SetNavigationalProperties(account);
                }
            }

            return account;
        }

        public void CreateUserProvider(Account account, UserProvider provider)
        {
            //using (MXHEntities context = conn.GetContext())
            //{
            //    UserProvider up = new UserProvider();
            //    ap.AccountID = account.AccountID;
            //    ap.PermissionID = permission.PermissionID;
            //    context.AccountPermissions.AddObject(ap);
            //    context.SaveChanges();
            //}
        }

        public void CreateProfileForAccount(Account account)
        {
            using (MXHEntities context = new MXHEntities())
            {
                Profile profile = new Profile();
                profile.AccountID = account.AccountID;
                profile.ProfileName = "profile_" + account.AccountID.ToString();
                profile.CreateDate = DateTime.Now;
                context.Profiles.AddObject(profile);
                context.SaveChanges();
            }
        }

        public void AddPermission(Account account, Permission permission)
        {
            using(MXHEntities context = conn.GetContext())
            {
                AccountPermission ap = new AccountPermission();
                ap.AccountID = account.AccountID;
                ap.PermissionID = permission.PermissionID;
                context.AccountPermissions.AddObject(ap);                         
                context.SaveChanges();
            }
        }

        public void SaveAccount(Account account)
        {
            using(MXHEntities context = conn.GetContext())
            {
                if(account.AccountID > 0)
                {
                    context.Accounts.Attach(new Account { AccountID = account.AccountID });
                    context.Accounts.ApplyCurrentValues(account);
                }
                else
                {
                    context.Accounts.AddObject(account);
                }
                context.SaveChanges();
            }
        }        

        public void DeleteAccount(Account account)
        {
            using (MXHEntities context = conn.GetContext())
            {
                context.Accounts.DeleteObject(account);
                context.SaveChanges();
            }
        }

        public List<Account> GetAllAccounts(Int32 PageNumber, Int32 pageSize)
        {
            IEnumerable<Account> accounts = null;

            using (MXHEntities context = conn.GetContext())
            {
                accounts = (from a in context.Accounts.Include("Profiles")
                                orderby a.Username
                               select a).Skip((PageNumber - 1) * pageSize).Take(pageSize);
            }
            return accounts.ToList();
        }

        private static void SetNavigationalProperties(Account account)
        {
            account.Profile = account.Profiles.FirstOrDefault();
        }

        public List<Account> GetAccountsByAccountIDList(List<Int32> accountIDs)
        {
            List<Account> result = new List<Account>();
            using (MXHEntities context = conn.GetContext())
            {
                accountIDs.ForEach(n => result.Add(this.GetAccountByID(n)));
            }
            return result;
        }

        public bool UpdatePassword(int accountID, string password)
        {
            Account account = null;

            using (MXHEntities context = conn.GetContext())
            {
                account = (from a in context.Accounts
                           where a.AccountID == accountID
                           select a).FirstOrDefault();
                if (account != null)
                {
                    account.Password = password;
                    context.SaveChanges();                    
                    return true;
                }
            }
            return false;
        }

        public bool CheckPassword(string accountID, string password)
        {
            Account account = null;
            int id = Convert.ToInt32(accountID);
            using (MXHEntities context = conn.GetContext())
            {
                account = (from a in context.Accounts
                           where a.AccountID == id && a.Password == password
                           select a).FirstOrDefault();
                if (account != null)
                {
                    return true;
                }
            }
            return false;
        }

        public List<Account> GetRandomListAccount()
        {
            List<Account> lstRandomAccounts = new List<Account>();                        
                        
            using (MXHEntities context = conn.GetContext())
            {                
                var allAccounts = (from acc in context.Accounts
                                  select acc).Take(10);
                if (allAccounts != null)
                    lstRandomAccounts = allAccounts.ToList();
            }            
            return lstRandomAccounts;
        }

        public List<Account> GetListAccountsByTextSearch(string text)
        {
            List<Account> lstAccount = new List<Account>();

            string[] arrayStr = text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string str in arrayStr)
            {
                string strSQL = @"select * 
                              from Account 
                              where FirstName collate SQL_Latin1_General_Cp1_CI_AI like '%" + str + "%' or" + @"
                                    MidName collate SQL_Latin1_General_Cp1_CI_AI like '%" + str + "%' or" + @"
                                    LastName collate SQL_Latin1_General_Cp1_CI_AI like '%" + str + "%' " + @"
                              order by FirstName";
                string strSQL_username = @"select * from Account where Username like '%"+ str +"%'";

                using (MXHEntities context = conn.GetContext())
                {
                    var accounts = context.ExecuteStoreQuery<Account>(strSQL);
                    if (accounts != null)
                        lstAccount.AddRange(accounts.ToList());

                    accounts = context.ExecuteStoreQuery<Account>(strSQL_username);
                    if (accounts != null)
                        lstAccount.AddRange(accounts.ToList());
                }
            }
            lstAccount = lstAccount.GroupBy(n => n.AccountID).Select(m => m.First()).ToList();
            return lstAccount;
        }

        public int CheckAccountByAccountID(int accountID, int friendAccountID)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var friend = from fr in context.Friends
                            where (fr.AccountID == accountID && fr.MyFriendsAccountID == friendAccountID) ||
                                    (fr.MyFriendsAccountID == accountID && fr.AccountID == friendAccountID)
                            select fr;
                if (friend.Count() > 0)
                    return -1;

                var friendIn = from fr in context.FriendsInvitations
                            where fr.AccountID == accountID && fr.BecameAccountID == friendAccountID                                                   
                            select fr;
                if (friendIn.Count() > 0)
                    return 0;
            }
            return 1;
        }

        public int GetCountLoginByUsername(string username)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.Username == username
                           select acc;
                Account account = item.FirstOrDefault();
                return Convert.ToInt32(account.CountLogin);
            }
        }

        public void UpdateCountLoginByUsername(string username)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.Username == username
                           select acc;
                Account account = item.FirstOrDefault();
                account.CountLogin++;
                context.SaveChanges();
            }
        }

        public void ResetCountLoginByUsername(string username)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.Username == username
                           select acc;
                Account account = item.FirstOrDefault();
                account.CountLogin = 0;
                context.SaveChanges();
            }
        }

        public void IsLockAccount(string username,bool isLock)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.Username == username
                           select acc;
                Account account = item.FirstOrDefault();
                account.IsLock = isLock;
                context.SaveChanges();
            }
        }

        public void UpdateLevelAccountByAccountID(int accountID, int levelID)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                if (item.Count() > 0)
                {
                    Account account = item.FirstOrDefault();
                    account.LevelID = levelID;
                    context.SaveChanges();
                }
            }
        }

        public void UpdateScoreAccountByAccountID(int accountID, int score)
        {            
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                if (item.Count() > 0)
                {
                    Account account = item.FirstOrDefault();
                    account.Score = score;
                    context.SaveChanges();
                }
            }
        }

        public List<Account> GetAllAccounts()
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           select acc;
                return item.Count() > 0 ? item.ToList() : null;
            }
        }

        public void UpdateMember_AdminPage(int accountID, int levelID, bool isLock)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                if (item.Count() > 0)
                {
                    Account account = item.FirstOrDefault();
                    account.LevelID = levelID;
                    account.IsLock = isLock;
                    context.SaveChanges();
                }
            }
        }

        public void DeleteAccountByAccountID(int accountID)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                if (item.Count() > 0)
                {
                    Account account = item.FirstOrDefault();
                    context.Accounts.DeleteObject(account);
                    context.SaveChanges();
                }
            }
        }

        public string GetPlainTextByAccountID(int accountID)
        {
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                return item.Count() > 0 ? item.FirstOrDefault().Plaintext : "";
            }
        }

        public int GetLevelIDByAccountID(int accountID)
        {                        
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                return item.Count() > 0 ? Convert.ToInt32(item.FirstOrDefault().LevelID) : -1;
            }
        }

        public int GetScoreByAccountID(int accountID)
        {            
            using (MXHEntities context = conn.GetContext())
            {
                var item = from acc in context.Accounts
                           where acc.AccountID == accountID
                           select acc;
                return item.Count() > 0 ? Convert.ToInt32(item.FirstOrDefault().Score) : -1;
            }
        }
    }
}
